<?php

namespace App\Service\Cruise\Check;

use App\Enums\Common\CommonEnum;
use App\Library\Rms\RmsShopApi;
use App\Library\Rms\RmsUserApi;
use App\Models\BaseModel;
use App\Models\Cruise\CruiseCheckAgainstModel;
use App\Models\Cruise\CruiseCheckDetailModel;
use App\Models\Cruise\CruiseCheckRectifyModel;
use App\Models\Cruise\CruiseCheckTaskModel;
use App\Models\Cruise\CruiseOrderInputModel;
use App\Models\Cruise\CruiseOrderModel;
use App\Models\Cruise\CruiseOrderProcessModel;
use App\Models\Cruise\CruiseTemplateModel;
use App\Models\OpenShop\InvestmentPromotion\OpenShopAddressModel;
use App\Models\OpenShop\InvestmentPromotion\OpenShopSignOrderModel;
use App\Service\BaseService;
use App\Service\Cruise\Mission\CheckInputService;
use Carbon\Carbon;
use GuzzleHttp\Exception\GuzzleException;
use Illuminate\Support\Facades\Cache;

class CruiseCheckDetailService
{

    /**
     * 稽核报告列表展示
     * @param $orderPermission
     * @param $pageSize
     * @param $pageNum
     * @param $shopCode
     * @param $name
     * @param $status
     * @param $type
     * @param $level
     * @param $cityCode
     * @param int $templateType
     * @param int $shopId
     * @return array
     * @throws GuzzleException
     */
    public static function getCheckDetailList($orderPermission, $pageSize, $pageNum, $shopCode, $name, $status, $type, $level, $cityCode, int $templateType, int $shopId = 0, array $paramArr = []): array
    {
        $basicOrderIdSql = self::getBasicPermissionSql($templateType, $name, $shopCode, $cityCode, $orderPermission, $shopId);

        $cruiseCheckDetail = CruiseCheckDetailModel::query()
            ->orderByDesc('createdAt')
            ->whereRaw("orderId in (" . $basicOrderIdSql . ")")
            ->whereIn('reportResult', [CruiseCheckDetailModel::REPORT_RESULT_QUALIFIED, CruiseCheckDetailModel::REPORT_RESULT_UNQUALIFIED]);

        // 任务类型统计
        $getTemplateCount = function ($query, $template) {
            return (clone $query)
                ->when($template !== false, function ($q) use ($template) {
                    $q->where('sysTemplate', $template);
                })
                ->count();
        };

        // 是否合格统计
        $getTypeAndResultCount = function ($query, $type, $result) {
            return (clone $query)
                ->when(mb_strlen($type), function ($q) use ($type) {
                    $q->where('sysTemplate', $type);
                })
                ->when($result !== false, function ($q) use ($result) {
                    $q->where('reportResult', $result);
                })
                ->count();
        };

        // 如果是全部权限 进行缓存 并且拿缓存的数据
        if ($orderPermission['isAll']) {
            $paramMd5          = md5(json_encode(array_merge($paramArr, ['shopId' => $shopId, 'shopCode' => $shopCode])));
            $dashboardTemplate = Cache::remember($paramMd5 . 'Template', 600, function () use ($getTemplateCount, $cruiseCheckDetail) {
                return [
                    'taskTotal'      => $getTemplateCount($cruiseCheckDetail, false),
                    'selfTest'       => $getTemplateCount($cruiseCheckDetail, CruiseTemplateModel::SYS_TEMPLATE_FACTORY_SELF),
                    'specialProject' => $getTemplateCount($cruiseCheckDetail, CruiseTemplateModel::SYS_TEMPLATE_FACTORY_SPECIAL),
                ];
            });
            $dashboardStatus = Cache::remember($paramMd5 . 'Status', 600, function () use ($getTypeAndResultCount, $type, $cruiseCheckDetail) {
                return [
                    'statusTotal' => $getTypeAndResultCount($cruiseCheckDetail, $type, false),
                    'qualified'   => $getTypeAndResultCount($cruiseCheckDetail, $type, CruiseCheckDetailModel::REPORT_RESULT_QUALIFIED),
                    'unQualified' => $getTypeAndResultCount($cruiseCheckDetail, $type, CruiseCheckDetailModel::REPORT_RESULT_UNQUALIFIED),
                ];
            });

        } else {
            $dashboardTemplate = [
                'taskTotal'      => $getTemplateCount($cruiseCheckDetail, false),
                'selfTest'       => $getTemplateCount($cruiseCheckDetail, CruiseTemplateModel::SYS_TEMPLATE_FACTORY_SELF),
                'specialProject' => $getTemplateCount($cruiseCheckDetail, CruiseTemplateModel::SYS_TEMPLATE_FACTORY_SPECIAL),
            ];
            $dashboardStatus   = [
                'statusTotal' => $getTypeAndResultCount($cruiseCheckDetail, $type, false),
                'qualified'   => $getTypeAndResultCount($cruiseCheckDetail, $type, CruiseCheckDetailModel::REPORT_RESULT_QUALIFIED),
                'unQualified' => $getTypeAndResultCount($cruiseCheckDetail, $type, CruiseCheckDetailModel::REPORT_RESULT_UNQUALIFIED),
            ];
        }

        $paginator       = $cruiseCheckDetail
            ->when(mb_strlen($type), function ($query) use ($type) {
                $query->where('sysTemplate', $type);
            })
            ->when($status, function ($query) use ($status) {
                $query->where('reportResult', $status);
            })
            ->with([
                'cruiseOrderRel.cruiseCheckCompanyRel.fsCompanyRel',
                'cruiseCheckAgainst' => function($query) {
                    $query->where('status', CruiseCheckAgainstModel::STATUS_WAIT);
                },
                'cruiseCheckRectify' => function($query) {
                    $query->whereIn('status', [CruiseCheckRectifyModel::STATUS_WAIT_SUBMIT, CruiseCheckRectifyModel::STATUS_WAIT_AUDIT]);
                },
                'cruiseTaskRel',
                'cruiseCheckSelfDetailRel.cruiseCheckSelfTaskRel',
            ])
            ->paginate($pageSize, ['*'], 'pageNum', $pageNum);

        $cruiseOrderData = $paginator->pluck('cruiseOrderRel')->toArray();
        $shopIds         = collect($cruiseOrderData)->pluck('shopId')->toArray();
        $shopList        = array_column((new RmsShopApi())->getShopByIds($shopIds, ['id', 'shopCode', 'name'])['data']['shopList'] ?? [], null, 'id');
        $list            = $paginator->map(function (CruiseCheckDetailModel $checkDetailModel) use ($shopList, $templateType) {
            $tip  = '';
            if (count($checkDetailModel->cruiseCheckRectify)) {
                $tip  = '整改中';
            }
            if (count($checkDetailModel->cruiseCheckAgainst)) {
                $tip  = '违约函';
            }
            return [
                'id'           => $checkDetailModel->id,
                'shopInfo'     => $templateType == CruiseOrderModel::TYPE_CHECK ? ('KF' . sprintf("%04d", ($shopList[$checkDetailModel->cruiseOrderRel->shopId]['shopCode'] ?? '0000')) . ' ' . ($shopList[$checkDetailModel->cruiseOrderRel->shopId]['name'] ?? '-')) : '',
                'code'         => $checkDetailModel->code,
                'statusText'   => CruiseCheckDetailModel::REPORT_RESULT_MAPPING[$checkDetailModel->reportResult] ?? '-',
                'status'       => $checkDetailModel->reportResult,
                'totalNum'     => $checkDetailModel->totalNum,
                'tip'          => $tip,
                'rectifyCount' => count($checkDetailModel->cruiseCheckRectify),
                'failNum'      => $checkDetailModel->failNum,
                'createdAt'    => $checkDetailModel->createdAt->toDateString(),
                'handler'      => $checkDetailModel->dealName,
                'companyName'  => (string)optional(optional(optional($checkDetailModel->cruiseOrderRel)->cruiseCheckCompanyRel)->fsCompanyRel)->name,
                'taskName'     => $checkDetailModel->cruiseOrderRel->getTaskName($checkDetailModel->taskId),
                'qualityScore' => $checkDetailModel->qualityScore,  //督导评分
            ];
        });

        return [
            'list'           => $list,
            'count'          => $paginator->total(),
            'qualified'      => $dashboardStatus['qualified'] ?? 0,
            'unQualified'    => $dashboardStatus['unQualified'] ?? 0,
            'statusTotal'    => $dashboardStatus['statusTotal'] ?? 0,
            'taskTotal'      => $dashboardTemplate['taskTotal'] ?? 0,
            'selfTest'       => $dashboardTemplate['selfTest'] ?? 0,
            'specialProject' => $dashboardTemplate['specialProject'] ?? 0,
            'pageNum'        => $pageNum,
            'pageSize'       => $pageSize,
        ];
    }

    /**
     * 稽核报告详情
     * @param $id
     * @param $authInfo
     * @return array
     * @throws GuzzleException
     */
    public static function detail($id, $authInfo, int $platform = CommonEnum::PLATFORM_FS_MINI): array
    {
        $cruiseCheckDetailQuery = CruiseCheckDetailModel::query()
            ->with(['cruiseOrderRel.cruiseCheckCompanyRel.fsCompanyRel', 'cruiseCheckAgainst', 'cruiseCheckRectify'])
            ->find($id);

        if (null == $cruiseCheckDetailQuery) {
            return [];
        }
        $shopList = array_column((new RmsShopApi())->getShopByIds([(int)optional($cruiseCheckDetailQuery->cruiseOrderRel)->shopId], ['id', 'shopCode', 'name'])['data']['shopList'] ?? [], null, 'id');

        $handlerId = 0;
        if ($cruiseCheckDetailQuery->templateType == CruiseTemplateModel::TYPE_8) {
            $handlerId  = $cruiseCheckDetailQuery->createdByUid;
        }

        $userDetail = (new RmsUserApi())->getUserInfoByIds([$cruiseCheckDetailQuery->dealUid, $handlerId])['data'] ?? [];
        $userInfo = collect($userDetail)->where('id', $cruiseCheckDetailQuery->dealUid)->first();

        //判断是否有违约函
        $againstId = 0;
        $isAgainst = false;
        $unusualInfo = [];
        if (count($cruiseCheckDetailQuery->cruiseCheckAgainst)) {
            foreach ($cruiseCheckDetailQuery->cruiseCheckAgainst as $cruiseCheckAgainst) {
                if ($cruiseCheckAgainst->status == CruiseCheckAgainstModel::STATUS_WAIT) {
                    $isAgainst = true;
                    $unusualInfo = [
                        'tip'        => '违约函',
                        'endTime'    => formatDate($cruiseCheckAgainst->endTime),
                        'againstId'  => $cruiseCheckAgainst->id,
                        'level'      => $cruiseCheckAgainst->level,
                    ];
                } else {
                    $againstId = $cruiseCheckAgainst->id;
                }
            }
        }
        $tip           = false;
        $submitEndTime = '';
        $rectifyStatus = CruiseCheckRectifyModel::REPORT_RECTIFY_STATUS_NONE;
        if (count($cruiseCheckDetailQuery->cruiseCheckRectify)) {
            $rectifyStatus = CruiseCheckRectifyModel::REPORT_RECTIFY_STATUS_FINISH;
            //存在整改单  获得整改单的过期时间
            foreach ($cruiseCheckDetailQuery->cruiseCheckRectify as $cruiseCheckRectify) {
                if ($cruiseCheckRectify->status == CruiseCheckRectifyModel::STATUS_WAIT_SUBMIT && $cruiseCheckRectify->submitEndTime < time()) {
                    $tip           = true;
                    $submitEndTime = date('Y-m-d H:i:s', $cruiseCheckRectify->submitEndTime);
                }
                if (in_array($cruiseCheckRectify->status, [CruiseCheckRectifyModel::STATUS_WAIT_AUDIT, CruiseCheckRectifyModel::STATUS_WAIT_SUBMIT])) {
                    $rectifyStatus = CruiseCheckRectifyModel::REPORT_RECTIFY_STATUS_ING;
                }
            }
        }

        // 区分处理人
        $managerInfo = [];
        if ($cruiseCheckDetailQuery->templateType == CruiseTemplateModel::TYPE_8) {
            $managerInfo = [
                'name'     => collect($userDetail)->where('id', $handlerId)->first()['username'] ?? '',
                'number'   => '',
                'position' => '',
                'photo'    => picturePath('4b/07/1e16179f2dfe445f9eaa559e81d204fd6c6f70049642a72dfd42108990dd.jpg'),
            ];
        } else {
            $managerInfo = [
                'name'     => $platform == CommonEnum::PLATFORM_MERCHANT ? '夸父品控' : $userInfo['username'] ?? '-',
                'number'   => CruiseOrderService::getCheckNoByUserId($userInfo['id'] ?? 0),
                'position' => $userInfo['fs_user_rel'][0]['jobTitle'] ?? '-',
                'photo'    => picturePath(($userInfo['photo'] ?? '4b/07/1e16179f2dfe445f9eaa559e81d204fd6c6f70049642a72dfd42108990dd.jpg') ?: '4b/07/1e16179f2dfe445f9eaa559e81d204fd6c6f70049642a72dfd42108990dd.jpg'),
            ];
        }


        return [
            'shopInfo'     => $cruiseCheckDetailQuery->templateType == CruiseOrderModel::TYPE_CHECK ? ('KF' . sprintf("%04d", ($shopList[$cruiseCheckDetailQuery->cruiseOrderRel->shopId]['shopCode'] ?? '0000')) . ' ' . ($shopList[$cruiseCheckDetailQuery->cruiseOrderRel->shopId]['name'] ?? '-')) : '',
            'companyName'  => object_get($cruiseCheckDetailQuery->cruiseOrderRel, 'cruiseCheckCompanyRel.fsCompanyRel.name', '-'),
            'statusText'   => CruiseCheckDetailModel::REPORT_RESULT_MAPPING[$cruiseCheckDetailQuery->reportResult] ?? '-',
            'status'       => $cruiseCheckDetailQuery->reportResult,
            'totalNum'     => $cruiseCheckDetailQuery->totalNum,
            'code'         => $cruiseCheckDetailQuery->code,
            'failNum'      => $cruiseCheckDetailQuery->failNum,
            'createdAt'    => $cruiseCheckDetailQuery->createdAt->toDateString(),
            'totalScore'   => $cruiseCheckDetailQuery->totalScore,
            'successScore' => $cruiseCheckDetailQuery->successScore,
            'actualScore'  => $cruiseCheckDetailQuery->actualScore,
            'againstId'    => $againstId,
            'isAgainst'    => $isAgainst,
            'unusualInfo'  => $unusualInfo,
            'submitEndTime'=> $submitEndTime,
            'tip'          => $tip,
            'rectifyStatus'=> $rectifyStatus,
            'managerInfo'  => $managerInfo,
            'auditInfo' => [
                'name'     => (new CheckInputService($cruiseCheckDetailQuery->orderId))->getCurrentHandlerInfo(CruiseOrderProcessModel::PROCESS_REVIEWED)['userNames'] ?? '-',
                'position' => '夸父品控',
                'photo'    => picturePath('4b/07/1e16179f2dfe445f9eaa559e81d204fd6c6f70049642a72dfd42108990dd.jpg'),
            ],
            //'inputs'       => (new CheckInputService($cruiseCheckDetailQuery->cruiseOrderRel->id, $authInfo['userId']))->getInputObjectFill()
            'inputs'       => [
                'lists'    => (new CruiseCheckRectifyService(0, 0))->reportsLists($cruiseCheckDetailQuery->id, CruiseCheckRectifyModel::STATUS_WAIT_TOTAL, false),
                'classify' => (new CruiseCheckRectifyService(0, 0))->reportsListsGroupByRectifyStatus($cruiseCheckDetailQuery->id),
            ]
        ];
    }

    public static function count($authInfo, int $templateType)
    {
        $qualified   = 0;
        $unQualified = 0;
        CruiseCheckDetailModel::query()
            ->where('templateType', $templateType)
            ->whereIn('reportResult', [CruiseCheckDetailModel::REPORT_RESULT_QUALIFIED, CruiseCheckDetailModel::REPORT_RESULT_UNQUALIFIED])
            ->each(function (CruiseCheckDetailModel $checkDetailModel) use (&$qualified, &$unQualified) {
                if ($checkDetailModel->reportResult == CruiseCheckDetailModel::REPORT_RESULT_QUALIFIED) {
                    ++$qualified;
                }
                if ($checkDetailModel->reportResult == CruiseCheckDetailModel::REPORT_RESULT_UNQUALIFIED) {
                    ++$unQualified;
                }
            });
        return [
            'qualified'   => $qualified,
            'unQualified' => $unQualified,
        ];
    }

    /**
     * 获得权限控制下的SQL
     */
    public static function getBasicPermissionSql($templateType, $name, $shopCode, $cityCode, $orderPermission, $shopId): string
    {
        $basicSql  = CruiseOrderModel::query()
            ->where('type', $templateType)
            ->orderByDesc('updatedAt')
            ->when(mb_strlen($name), function ($query) use ($name) {
                $query->whereRaw("orderNo in (select `orderNo` from `open_shop_user_identity_card` where `name` = '{$name}')");
            })
            ->when(mb_strlen($shopCode), function ($query) use ($shopCode) {
                $child = OpenShopSignOrderModel::query()
                    ->where('shopCode', $shopCode)
                    ->select('orderNo');
                $query->whereRaw("cruise_order.orderNo in (" . BaseModel::toSqlWithParam($child) . ')');
            })
            ->when($cityCode, function ($query) use ($cityCode) {
                $child = OpenShopAddressModel::query()
                    ->where('cityCode', $cityCode)
                    ->select('orderNo');
                $query->whereRaw("cruise_order.orderNo in (" . BaseModel::toSqlWithParam($child) . ')');
            })
            ->when(!$orderPermission['isAll'], function ($query) use ($orderPermission) {
                $query->whereRaw($orderPermission['rawSql']);
            })
            ->when($shopId, function ($query) use ($shopId) {
                $query->where("shopId", $shopId);
            })
            ->select('id');

        return BaseModel::toSqlWithParam($basicSql);
    }

}
